//  OpenCVDLL.cpp
//
//  OpenCV Wrapper functions for Mayhem motion detector
//
// (c) 2010/2011 Microsoft Applied Sciences Group
// Author: Sven Kratz

#include "stdafx.h"
#include "OpenCVDLL.h"

using namespace OpenCVDLL;

///// MotionDetector Module

	MotionDetector::MotionDetector(int width, int height)
	{

		Debug::WriteLine("[MotionDetector(C++/CLI)] : ctor");

#ifdef DEBUG
		printf("[MotionDetector::MotionDetector]\n");
#endif

		// initialize image buffers
		CvSize imgSize = cvSize(width,height);
		movingAverage = cvCreateImage( imgSize, IPL_DEPTH_32F, 3);
		diffGray = cvCreateImage( cvSize(width,height), IPL_DEPTH_8U, 1);
		difference = cvCreateImage(cvSize(width, height), 8, 3);
		first = true;
		w = width;
		h = height; 
#ifdef DEBUG
		printf("[MotionDetector::MotionDetector] --- DONE!\n");
#endif
	}

	MotionDetector::~MotionDetector()
	{
		Debug::WriteLine("[MotionDetector(C++/CLI)] : dtor");
		IplImage * dGray = diffGray;
		IplImage * diff = difference;
		IplImage * mAvg = movingAverage;
		IplImage * tmp = temp;
		cvReleaseImage(&dGray); 
		cvReleaseImage(&diff);
		cvReleaseImage(&mAvg);
		cvReleaseImage(&tmp);
	}


	void MotionDetector::ProcessFrame(unsigned char * imageData, int * contourBoundPoints, int & numContours)
	{

	
		IplImage * img  = cvCreateImage(cvSize(w,h), 8,3);
		img->imageData = (char*) imageData;

		if (first)
		{
			
			temp = cvCloneImage(img);
			//cvConvertScale(currentImage, movingAverage, 1.0, 0.0);
			first = false;
			cvReleaseImage(&img);
			return;
		}

		cvRunningAvg(img, movingAverage, 0.02, 0);
		cvConvertScale(movingAverage, temp, 1.0, 0.0);
		cvAbsDiff(img, temp, difference);
		cvCvtColor(difference,diffGray, CV_RGB2GRAY);

		cvSmooth(diffGray, diffGray, CV_GAUSSIAN,3,3);
		cvThreshold(diffGray, diffGray, 70, 255, CV_THRESH_BINARY);
		cvDilate(diffGray, diffGray, 0, 18);
		cvErode(diffGray, diffGray, 0, 10);

		////////////////////////////////
		IplImage * grayCtr = cvCloneImage(diffGray);
		////////////////////////////////

		// contours
		////////////////////////////////
		CvMemStorage * storage = cvCreateMemStorage(0);
		///////////////////////////////
		CvSeq * contour = 0;

		cvFindContours( grayCtr, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
	
		if (contour == 0)
		{
			numContours = 0;		
		}
		else
		{
			int numPoints = contour->total * 4;
			#ifdef DEBUG
					printf("Number of boundingRectPoints: %d \n", numPoints);
			#endif

			//numContours = numPoints;
		
			CvRect bndRect = cvRect(0,0,0,0);
			int prevX;

			// contour array index
			int cIdx = 0;	
		
			for( ; contour != 0; contour = contour->h_next )
			{

				CvPoint pt1;
				CvPoint pt2;

				//Get a bounding rectangle around the moving object.
				bndRect = cvBoundingRect(contour, 0);

				pt1.x = bndRect.x;
				pt1.y = bndRect.y;
				pt2.x = bndRect.x + bndRect.width;
				pt2.y = bndRect.y + bndRect.height;

				contourBoundPoints[cIdx++] = pt1.x;
				contourBoundPoints[cIdx++] = pt1.y;
				contourBoundPoints[cIdx++] = pt2.x;
				contourBoundPoints[cIdx++] = pt2.y;
	#ifdef DEBUG
				printf("x1 %d y1 %d x2 %d y2 %d\n", pt1.x, pt1.y, pt2.x, pt2.y);
	#endif
			
			}
		
			numContours = cIdx;
		}
		/////////////////////////////////////
		// release memory

		cvReleaseImage(&grayCtr);
		cvReleaseImage(&img);
		cvFree(&storage);
		cvFree(&contour);
	}
